package main

import (
	"container/list"
	"fmt"
	"time"
	"math/big"
	"math"
)

const M uint64 = 600851475143

//const M uint64 = 13195
//const M int = 1000
//const n int = 62113
const n int = 2000000

var primesList *list.List
var isMultiple bool = false
var sum *big.Int
var summ uint64 = 0

func init() {
	primesList = list.New()
	sum = big.NewInt(0)
}

func main() {
	start := time.Now()
	ch := make(chan int)
	go nextPrime(ch)
	i := 0
	a := <- ch 
	sum = sum.Add(sum, big.NewInt(int64(a)))
	summ += uint64(a)
	fmt.Printf("prime #%v = %v\n", i+1, a)
	for a < n {
		a = <- ch 
		sum = sum.Add(sum, big.NewInt(int64(a)))
		summ += uint64(a)
		i++
		fmt.Printf("prime #%v = %v\n", i+1, a)
	}
	//fmt.Printf("Sum = %v\n", sum.String())
	fmt.Printf("sum =  %v\n", summ-uint64(a))
	stop := time.Now()
	fmt.Println("Execution time: ", stop.Sub(start))
}

func nextPrime(ch chan int) {
	multiple := false
	primes := list.New()
	ch <- 2
	ch <- 3
	ch <- 5
	i := 6
	for {
		if (i%2 == 0) || (i%3 == 0) || (i%5 == 0) {
			i++
			continue
		}
		if i > 48 {
			for e := primes.Front(); e != nil; e = e.Next() {
				if e.Value.(int) <= int(math.Sqrt(float64(i)))  {
					if i%e.Value.(int) == 0 {
						multiple = true
						break
					}
				} else {
					multiple = false
					break
				}
			}
			if multiple {
				i++
				multiple = false
				continue
			}

		}
		primes.PushBack(i)
		ch <- i
		i++
	}
}
